%{
  #include <stdio.h>
  int yylex (void);
  int yyerror(const char*);
%}

%token IF
%token ELSE
%token MAIN
%token VOID
%token FOR
%token GOTO
%token COUT
%token CIN
%token OR
%token AND
%token NOT
%token VECTOR

%token TYPE_BASE
%token INTEGER
%token FLOAT
%token BOOL

%token IDENTIFIER

%token ASSIGN_OPERATOR
%token RELATION
%token VSIZE_OPERATOR
%token UNARY_OPERATOR
%left ADD_OPERATOR
%left MULT_OPERATOR
%right UMINUS

%%
Program: VOID MAIN '(' ')' '{' DeclarVar DeclarVector SeqOperator '}'
  ;

DeclarVar:
  | TYPE_BASE IDENTIFIER ';' DeclarVar
  ;
  
DeclarVector:
  | VECTOR IDENTIFIER '[' INTEGER ']' ';' DeclarVector {push}
  ;
  
SeqOperator:
  | Operator SeqOperator
  ;
  
Operator: Label ':' NonMarkedOperator
  | NonMarkedOperator
  ;
  
NonMarkedOperator: CompositeOperator
  | AssignOperator 
  | ConditionOperator
  | LoopOperator
  | GotoOperator
  | InputOperator
  | OutputOperator
  | UnaryOperation ';'
  ;

CompositeOperator: '{' SeqOperator '}'
  ;

AssignOperator: Var ASSIGN_OPERATOR Expr ';'
  | Var ASSIGN_OPERATOR ConAssignOperator ';'
  | Var ASSIGN_OPERATOR Vector ';'
  ;

ConAssignOperator: Expr '?' Expr ':' Expr
  ;
  
ConditionOperator:  IF '(' Expr ')' Operator ElseExpr
 ;
 
ElseExpr:
 | ELSE Operator
 ;

LoopOperator: FOR '(' Operator ';' Expr ';' Operator ')' Operator
  ;
  
GotoOperator: GOTO Label ';'
  ;
  
InputOperator: CIN Var ';'
  ;
  
OutputOperator: COUT Var ';'
  ;

Expr: Expr ADD_OPERATOR Item
  | Relation
  | Expr OR Item
  | Item
  | UnaryOperation
  ;

UnaryOperation: Var UNARY_OPERATOR ;

Item: Item MULT_OPERATOR Factor
  | Item AND Factor
  | Factor
  | VSIZE_OPERATOR IDENTIFIER
  ;
  
Factor: Var {$$=$1}
  | '(' Expr ')'
  | INTEGER
  | FLOAT
  | BOOL
  | NOT Factor {int attr=createTemp(COperand::BOOL); pushTetr(CTetr(CTetr::NOT, attr, $2)); $$=attr;}
  | ADD_OPERATOR Factor %prec UMINUS {}
  ;
  
Relation: Expr RELATION Expr;

Var: IDENTIFIER {$$=}
  | VectorElem {//тетрада получения элемента массива}
  ;

Vector: '[' VectorElemDecl NVectorElemDecl ']' 
  ;

NVectorElemDecl:
  | ',' VectorElemDecl NVectorElemDecl
  ;
  
VectorElemDecl: Expr;

VectorElem: IDENTIFIER '[' Expr ']'
  ;

Label: '[' IDENTIFIER ']'
  ;
%%

#include "lang.cpp"

int main(int argc,char **argv)
{
  yydebug = 1;
  ++argv, --argc;  // skip over program name 
  yyin;
  if ( argc > 0 )
    yyin = fopen( argv[0], "r" );
  else
    yyin = stdin;

  return yyparse();  
}
